##############################
# STATE REACH AND DEVELOPMENT // PSRM // Replication
#
# Functions
#
##############################



# (function) Add line to latex table
latex.addline <- function(title,entries){c(title,paste0("\\multicolumn{1}{c}{",entries,"}"))}
latex.addline_nomc <- function(title,entries){c(title,entries)}

# (function) Mean of dependent variable for latex table
latex.mean.dv <- function(model.ls){
  c("Mean DV:",paste0("\\multicolumn{1}{c}{",signif(unlist(lapply(model.ls, function(m){mean(m$response)})), 2),"}"))
}

# (function) SD of dependent variable for latex table
latex.mean.sd <- function(model.ls){
  c("Std.-dev. DV:",paste0("\\multicolumn{1}{c}{",signif(unlist(lapply(model.ls, function(m){sd(m$response)})), 2),"}"))
}

# (function) Extract all coefficients from a list of felm models
extract_coef <- function(m.list){
  lapply(m.list, function(m){
    list(dv = colnames(m$coefficients),
         coef = m$coefficients,
         clustervcv = m$clustervcv)
  })
}

# (function) helper function to combine
make_form <- function(dv, expl, fe, iv = "0", se = "0" ){
  as.formula(paste(dv, "~", paste(expl, collapse = "+"), "|",
                   paste(fe, collapse = "+"), "|", iv, "|", se))
}

# (function) Generate Regression weights
gen_weights <- function(vec){
  tab <- table(vec)
  weights <- data.frame(cbind(weight = as.numeric(tab), unit = as.character(names(tab))),
                        stringsAsFactors = F)
  weight.vec <- 1/as.numeric(join(data.frame(unit = as.character(vec), stringsAsFactors = F),
                                  weights, type = "left", by = "unit")[,2])
  return(weight.vec)
  
}

# (function) Make coefficients with SE to nice text
effect_text <- function(coef, se, trans_fun = NULL, accuracy = 1){
  if(is.null(trans_fun)){
    paste0(signif(coef,accuracy),
           " [", signif(coef - se*1.95,accuracy),", ", 
           signif(coef + se*1.95,accuracy), "]")
  } else {
    paste0(signif(trans_fun(coef),accuracy),
           " [", signif(trans_fun(coef - se*1.95),accuracy),", ", 
           signif(trans_fun(coef + se*1.95),accuracy), "]")
  }
}


# (function) Make stargazer columnlabels with one extra layer and rulers
collab_w_ruler <- function(column.labels, column.separate, trim = 10, add.below = NULL){
  cmidrule <- paste(paste0("\\cmidrule(lr{",trim,"pt}){", c(2, 2 + cumsum(column.separate[-length(column.separate)])), "-",
                           c(1+ cumsum(column.separate)), "}"), collapse = " ")
  if(is.null(add.below)){
    result <-  c(column.labels[-length(column.labels)], 
                 paste0(column.labels[length(column.labels)], "} \\\\ ", cmidrule, " \\\\[-6ex] {"))
  } else {
    add.b <- paste(paste0(" & \\multicolumn{1}{c}{", add.below, "}"), collapse = "")
    result <-  c(column.labels[-length(column.labels)], 
                 paste0(column.labels[length(column.labels)], "} \\\\ ", cmidrule, add.b, " {"))
  }
  
  return(result)
}


# (function) Remove holes in SpatialPolygons
remove.holes <-  function(Poly, max.size = NULL){
  require(sp)
  
  # get holes
  holes <- lapply(Poly@polygons, function(x) sapply(slot(x, "Polygons"), slot,
                                                    "hole"))
  
  # subset by size
  size <- lapply(Poly@polygons, function(x) sapply(slot(x, "Polygons"), slot,
                                                   "area"))
  
  # Delete
  if(is.null(max.size)){
    res <- lapply(1:length(Poly@polygons), function(i) slot(Poly@polygons[[i]],
                                                            "Polygons")[!holes[[i]]])
  } else {
    res <- lapply(1:length(Poly@polygons), function(i) slot(Poly@polygons[[i]],
                                                            "Polygons")[!holes[[i]] | size[[i]] > max.size ])
  }
  
  # Finish
  IDs <- row.names(Poly)
  Polyfill <- SpatialPolygons(lapply(1:length(res), function(i)
    Polygons(res[[i]], ID=IDs[i])), proj4string=CRS(proj4string(Poly)))
  return(Polyfill)
}
